package com.ywk.base.common.util;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.*;
import com.microsoft.schemas.office.office.CTLock;
import com.microsoft.schemas.vml.*;
import org.apache.poi.wp.usermodel.HeaderFooterType;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.util.stream.Stream;

/**
 * word/pdf/img文件水印
 * @Author zbh
 * @Date 2024/1/8
 */
public class WaterMarkUtil {

    public static String PDF="application/pdf";
    public static String WORD="application/vnd.openxmlformats-officedocument.wordprocessingml.document";
    public static String IMG="image";


    public static void main(String[] args) throws DocumentException, IOException {
        String outputFile="D:\\Users\\YWK\\Desktop\\4.pdf";
//        String outputFile="D:\\ssssss\\123.docx";
//        String outputFile="D:\\ssssss\\123.jpg";
        FileOutputStream outputStream = new FileOutputStream(outputFile);

        waterMarkPdf("D:\\Users\\YWK\\Desktop\\3.pdf",outputStream,"测试水印\n测试第二行");
//        waterMarkWord("D:\\ssssss\\三线一单图层数据导入教程 - 副本.docx", outputStream, "测试水印印");
//        markImageByText("D:\\Users\\YWK\\Desktop\\th.jpg",outputStream,"水印水印",0);
    }


    // 水印透明度
    private static float alpha = 0.8f;

    // 水印文字字体
    private static Font font = new Font("微软雅黑", Font.BOLD, 30);

    // 水印文字颜色
    private static Color color = Color.BLACK;

    // 水印旋转角度
    private static final float rotation = 30;

    /**
     * PDF加文字水印
     *
     * @param inputFile     PDF文件输入路径
     * @param outputStream    PDF文件输出路径
     * @param waterMarkName 自定义水印
     */
    public static void waterMarkPdf(String inputFile, OutputStream outputStream, String waterMarkName) throws IOException, DocumentException {
        PdfReader reader = new PdfReader(inputFile);
//        FileOutputStream outputStream = new FileOutputStream(outputFile);
        PdfStamper stamper = new PdfStamper(reader, outputStream);
        //设置文字样式
        BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

        com.itextpdf.text.Rectangle pageRect = null;

        PdfGState gs = new PdfGState();
        //设置透明度
        gs.setFillOpacity(0.1f);

        gs.setStrokeOpacity(alpha);

        int total = reader.getNumberOfPages() + 1;

        JLabel label = new JLabel();

        //设置自定义水印
        label.setText(waterMarkName);

        for (int i = 1; i < total; i++) {


            PdfContentByte under = stamper.getOverContent(i);

            under.saveState();

            under.setGState(gs);

            under.beginText();

            under.setFontAndSize(base, font.getSize());


            pageRect = reader.getPageSize(i);
            float pageWidth = pageRect.getWidth();
            float pageHeight = pageRect.getHeight();

            // 计算水印位置，覆盖整个页面
            float x = 0;
            float y = 0;

            // 循环插入水印
            while (x < pageWidth && y < pageHeight) {
                under.showTextAligned(Element.ALIGN_CENTER, waterMarkName, x, y, rotation);
                // 水平平移
                x += 200;
                // 垂直平移
                if (x >= pageWidth) {
                    x = 0;
                    y += 200;
                }
            }

//            under.showTextAligned(Element.ALIGN_LEFT, waterMarkName, 300, 350, 40);
            // 添加水印文字
            under.endText();
        }
        //关闭流
        stamper.close();
        outputStream.close();
        reader.close();


    }

    /**
     *
     * @param inputFile 需要加水印的文件路径
     * @param os 出来的路径
     * @param watermark 自定义水印
     * @return
     */
    public static void waterMarkWord(String inputFile, OutputStream os, String watermark) {

        File tempFileDir = new File(inputFile);
        if (!tempFileDir.exists()) {
            tempFileDir.mkdirs();
        }
        //设置默认值
        String color = DEFAULT_FONT_COLOR;
        String fontSize = FONT_SIZE;
        String rotation = STYLE_ROTATION;
        XWPFDocument doc = null;

        try {
            doc = new XWPFDocument(Files.newInputStream(tempFileDir.toPath()));
//            doc = new HWPFDocument(Files.newInputStream(tempFileDir.toPath()));

            addWaterMark(doc, watermark, color, fontSize, rotation);
//            OutputStream os = new FileOutputStream(outputFile);
            doc.write(os);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("IO异常");
        } finally {
            if (doc != null) {
                try {
                    doc.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("IO异常");
                }
            }
        }
    }



    // 字体大小
    private static final String FONT_SIZE = "0.1pt";
    // 文本旋转角度
    private static final String STYLE_ROTATION = "-15";


    private static final String fontName = "PingFang SC"; // word字体

    private static final int widthPerWord = 10; // 一个字平均长度，单位pt，用于：计算文本占用的长度（文本总个数*单字长度）



    private final static String DEFAULT_FONT_COLOR = "#d8d8d8";


    /**
     * 添加水印信息
     *
     * @param obj
     * @param watermark
     * @param color
     * @param fontSize
     * @param rotation
     */
    private static void addWaterMark(Object obj, String watermark, String color, String fontSize, String rotation) {
        if (obj instanceof XWPFDocument) {
            XWPFDocument doc = (XWPFDocument) obj;
            makeFullWaterMarkByWordArt(doc, watermark, color, fontSize, rotation);
        }
    }


    /**
     * 以艺术字方式加上水印(平铺)
     *
     * @param docx       XWPFDocument对象
     * @param customText 水印文字
     */
    public static void makeFullWaterMarkByWordArt(XWPFDocument docx, String customText, String fontColor, String fontSize, String styleRotation) {
//        customText = customText + repeatString(" ", 16); // 水印文字之间使用8个空格分隔
//        customText = repeatString(customText, 10); // 一行水印重复水印文字次数
        String styleTop = "0pt";  // 与顶部的间距

        if (docx == null) {
            return;
        }
        // 遍历文档，添加水印

        String[] split = customText.split("\n");
        Integer type = 1;
        for (int lineIndex = -10; lineIndex < 20; lineIndex++) {
            for (int i = 0; i < split.length; i++) {
                styleTop = 150 * lineIndex+ i*20 + "pt";
                String text = split[i];
                text = text + repeatString(" ", 10); // 水印文字之间使用8个空格分隔
                text = repeatString(text, 20); // 一行水印重复水印文字次数
                waterMarkDocXDocument(docx, text, styleTop, type, fontColor, fontSize, styleRotation);
            }

        }
    }

    /**
     * 将指定的字符串重复repeats次.
     *
     * @param pattern 字符串
     * @param repeats 重复次数
     * @return 生成的字符串
     */
    private static String repeatString(String pattern, int repeats) {
        StringBuilder buffer = new StringBuilder(pattern.length() * repeats);
        Stream.generate(() -> pattern).limit(repeats).forEach(buffer::append);
        return new String(buffer);
    }


    /**
     * 为文档添加水印
     *
     * @param doc        需要被处理的docx文档对象
     * @param customText 水印文本
     * @param type       类型：1.平铺；2.单个
     */
    private static void waterMarkDocXDocument(XWPFDocument doc, String customText, String styleTop, int type, String fontColor, String fontSize, String rotation) {
        XWPFHeader header = doc.createHeader(HeaderFooterType.DEFAULT); // 如果之前已经创建过 DEFAULT 的Header，将会复用之
        int size = header.getParagraphs().size();
        if (size == 0) {
            header.createParagraph();
        }
        CTP ctp = header.getParagraphArray(0).getCTP();


        byte[] rsidr = doc.getDocument().getBody().getPArray(0).getRsidR();
        byte[] rsidrdefault = doc.getDocument().getBody().getPArray(0).getRsidRDefault();
        ctp.setRsidP(rsidr);
        ctp.setRsidRDefault(rsidrdefault);
        CTPPr ppr = ctp.addNewPPr();
        ppr.addNewPStyle().setVal("Header");
        // 开始加水印
        CTR ctr = ctp.addNewR();
        CTRPr ctrpr = ctr.addNewRPr();
        ctrpr.addNewNoProof();
        CTGroup group = CTGroup.Factory.newInstance();
        CTShapetype shapetype = group.addNewShapetype();
        CTTextPath shapeTypeTextPath = shapetype.addNewTextpath();
        shapeTypeTextPath.setOn(STTrueFalse.T);
        shapeTypeTextPath.setFitshape(STTrueFalse.T);
        CTLock lock = shapetype.addNewLock();
        lock.setExt(STExt.VIEW);
        CTShape shape = group.addNewShape();
        shape.setId("PowerPlusWaterMarkObject");
        shape.setSpid("_x0000_s102");
        shape.setType("#_x0000_t136");
        if (type != 2) {
            shape.setStyle(getShapeStyle(customText, styleTop, rotation)); // 设置形状样式（旋转，位置，相对路径等参数）
        } else {
            shape.setStyle(getShapeStyle()); // 设置形状样式（旋转，位置，相对路径等参数）
        }
        shape.setFillcolor(fontColor);
        shape.setStroked(STTrueFalse.FALSE); // 字体设置为实心
        CTTextPath shapeTextPath = shape.addNewTextpath(); // 绘制文本的路径
        shapeTextPath.setStyle("font-family:" + fontName + ";font-size:" + fontSize); // 设置文本字体与大小
        shapeTextPath.setString(customText);
        CTPicture pict = ctr.addNewPict();
        pict.set(group);
    }

    /**
     * 构建Shape的样式参数
     *
     * @param customText 水印文本
     * @return
     */
    private static String getShapeStyle(String customText, String styleTop, String styleRotation) {
        StringBuilder sb = new StringBuilder();
        sb.append("position: ").append("absolute"); // 文本path绘制的定位方式
        sb.append(";width: ").append(customText.length() * widthPerWord).append("pt"); // 计算文本占用的长度（文本总个数*单字长度）
        sb.append(";height: ").append("20pt"); // 字体高度
        sb.append(";z-index: ").append("-251654144");
        sb.append(";mso-wrap-edited: ").append("f");
        sb.append(";margin-top: ").append(styleTop);
        sb.append(";mso-position-horizontal-relative: ").append("margin");
        sb.append(";mso-position-vertical-relative: ").append("margin");
        sb.append(";mso-position-vertical: ").append("left");
        sb.append(";mso-position-horizontal: ").append("center");
        sb.append(";rotation: ").append(styleRotation);
        return sb.toString();
    }

    /**
     * 构建Shape的样式参数
     *
     * @return
     */
    private static String getShapeStyle() {
        StringBuilder sb = new StringBuilder();
        sb.append("position: ").append("absolute"); // 文本path绘制的定位方式
        sb.append(";left: ").append("opt");
        sb.append(";width: ").append("500pt"); // 计算文本占用的长度（文本总个数*单字长度）
        sb.append(";height: ").append("150pt"); // 字体高度
        sb.append(";z-index: ").append("-251654144");
        sb.append(";mso-wrap-edited: ").append("f");
        sb.append(";margin-left: ").append("-50pt");
        sb.append(";margin-top: ").append("270pt");
        sb.append(";mso-position-horizontal-relative: ").append("margin");
        sb.append(";mso-position-vertical-relative: ").append("margin");
        sb.append(";mso-width-relative: ").append("page");
        sb.append(";mso-height-relative: ").append("page");
        sb.append(";rotation: ").append("-2949120f");
        return sb.toString();
    }


    /**
     * 图片增加水印
     */
    /**
     * 给图片添加水印文字、可设置水印文字的旋转角度
     *
     * @param logoText
     * @param srcImgPath
     * @param os
     * @param degree
     */
    public static void markImageByText( String srcImgPath, OutputStream os, String logoText,Integer degree) {

        InputStream is = null;
        try {

            // 1、源图片
            Image srcImg = ImageIO.read(new File(srcImgPath));
            int width = srcImg.getWidth(null);
            int height = srcImg.getHeight(null);



            BufferedImage buffImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

            // 2、得到画笔对象
            Graphics2D g = buffImg.createGraphics();
            // 3、设置对线段的锯齿状边缘处理
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(
                    srcImg.getScaledInstance(srcImg.getWidth(null),
                            srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0, null);
            // 4、设置水印旋转
            if (null != degree) {
                // 旋转30度
                g.rotate(Math.toRadians(-30), width / 2, height / 2);
            }
            // 5、设置水印文字颜色
            g.setColor(color);
            // 6、设置水印文字Font
            g.setFont(font);
            // 7、设置水印文字透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
            // 8、第一参数->设置的内容，后面两个参数->文字在图片上的坐标位置(x,y)
            // x轴间距 应该改为动态计算字符串宽度
            int xHeight = 160;
            // y轴间距
            int yHeight = 80;
            // 设置水印的位置
            for (int i = 0; i < width / xHeight + 1; i+=5) {
                for (int j = 0; j < height / yHeight + 1; j+=5) {
                    g.drawString(logoText, i * xHeight, j * yHeight + font.getSize());
                }
            }

            // 9、释放资源
            g.dispose();


            // 10、生成图片
            ImageIO.write(buffImg, "jpeg", os);

            System.out.println("图片完成添加水印文字");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != is)
                    is.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (null != os)
                    os.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}
